﻿using System;
using System.ComponentModel;
using VNet.VisiSuite.Common.Resource;

namespace VNet.VisiSuite.VisiAdmin.Models
{
    /// <summary>
    /// ProductionPlanModel
    /// </summary>
    public class ProductionPlanModel : ComparableBaseModel<ProductionPlanModel>, IDataErrorInfo
    {
        #region Private Fields
        /// <summary>
        /// The _cell
        /// </summary>
        private CellModel _cell;
        /// <summary>
        /// The _cell identifier
        /// </summary>
        private int _cellId;
        /// <summary>
        /// The _work order
        /// </summary>
        private string _workOrder;
        /// <summary>
        /// The _product
        /// </summary>
        private ProductModel _product;
        /// <summary>
        /// The _product identifier
        /// </summary>
        private int _productId;
        /// <summary>
        /// The _production plan identifier
        /// </summary>
        private int _productionPlanId;
        /// <summary>
        /// The _due date
        /// </summary>
        private DateTime? _dueDate;
        /// <summary>
        /// The _planned
        /// </summary>
        private int _planned;
        /// <summary>
        /// The _actual
        /// </summary>
        private int _actual;
        /// <summary>
        /// The _closed
        /// </summary>
        private bool _closed;
        /// <summary>
        /// The _enabled
        /// </summary>
        private bool _enabled;
        /// <summary>
        /// The _sort order
        /// </summary>
        private int _sortOrder;
        /// <summary>
        /// The _created by
        /// </summary>
        private string _createdBy;
        /// <summary>
        /// The _created date
        /// </summary>
        private string _createdDate;
        /// <summary>
        /// The _last updated by
        /// </summary>
        private string _lastUpdatedBy;
        /// <summary>
        /// The _last updated date
        /// </summary>
        private string _lastUpdatedDate;
        /// <summary>
        /// The _braider product identifier
        /// </summary>
        private int? _braiderProductId;
        /// <summary>
        /// The _braider product
        /// </summary> 
        private BraiderProductModel _braiderProduct;
        /// <summary>
        /// The _cell description
        /// </summary>
        private string _cellDescription;
        /// <summary>
        /// The _product description
        /// </summary>
        private string _product_sku;
        /// <summary>
        /// The _braider product description
        /// </summary>
        private string _braiderProductDescription;

        #endregion

        #region Public Properties
        /// <summary>
        /// Gets or sets the cell.
        /// </summary>
        /// <value>
        /// The cell.
        /// </value>
        public CellModel Cell
        {
            get { return _cell; }
            set
            {
                _cell = value;
                CellDescription = _cell != null ? _cell.CellName : string.Empty;
                CellId = _cell != null ? _cell.CellId : 0;
                OnPropertyChanged("Cell");
            }
        }

        /// <summary>
        /// Gets or sets the cell identifier.
        /// </summary>
        /// <value>
        /// The cell identifier.
        /// </value>
        [Category("Properties")]
        [DisplayName("Cell")]
        [Description("The cell identifier.")]
        public int CellId
        {
            get { return _cellId; }
            set
            {
                _cellId = value;
                OnPropertyChanged("CellId",true);
            }
        }

        /// <summary>
        /// Gets or sets the work order.
        /// </summary>
        /// <value>
        /// The work order.
        /// </value>
        [Category("Properties")]
        [DisplayName("Work Order")]
        [Description("Work Order.")]
        public string WorkOrder
        {
            get { return _workOrder; }
            set
            {
                _workOrder = value;
                OnPropertyChanged("WorkOrder", true);
            }
        }

        /// <summary>
        /// Gets or sets the product.
        /// </summary>
        /// <value>
        /// The product.
        /// </value>
        public ProductModel Product
        {
            get { return _product; }
            set
            {
                _product = value;
                ProductSku = _product != null ? _product.Sku : string.Empty;
                ProductId = _product != null ? _product.ProductId : 0;
                OnPropertyChanged("Product");
            }
        }

        /// <summary>
        /// Gets or sets the product identifier.
        /// </summary>
        /// <value>
        /// The product identifier.
        /// </value>
        [Category("Properties")]
        [DisplayName("Product")]
        [Description("The product identifier.")]
        public int ProductId
        {
            get { return _productId; }
            set
            {
                _productId = value;
                OnPropertyChanged("ProductId", true);
            }
        }

        /// <summary>
        /// Gets or sets the braider product identifier.
        /// </summary>
        /// <value>
        /// The braider product identifier.
        /// </value>
        [Category("Properties")]
        [DisplayName("Braider Product")]
        [Description("The braider product identifier.")]
        public int? BraiderProductId
        {
            get { return _braiderProductId; }
            set
            {
                _braiderProductId = value;
                OnPropertyChanged("BraiderProductId", true);
            }
        }

        /// <summary>
        /// Gets or sets the braider product.
        /// </summary>
        /// <value>
        /// The braider product.
        /// </value>
        public BraiderProductModel BraiderProduct
        {
            get { return _braiderProduct; }
            set
            {
                _braiderProduct = value;
                BraiderProductDescription = _braiderProduct != null ? _braiderProduct.BraiderNumber.ToString() : string.Empty;
                BraiderProductId = _braiderProduct != null ? _braiderProduct.BraiderProductId : 0;
                OnPropertyChanged("BraiderProduct");
            }
        }

        /// <summary>
        /// Gets or sets the production plan identifier.
        /// </summary>
        /// <value>
        /// The production plan identifier.
        /// </value>
        public int ProductionPlanId
        {
            get { return _productionPlanId; }
            set
            {
                _productionPlanId = value;
                OnPropertyChanged("ProductionPlanId");
            }
        }

        /// <summary>
        /// Gets or sets the due date.
        /// </summary>
        /// <value>
        /// The due date.
        /// </value>
        [Category("Properties")]
        [DisplayName("Due Date")]
        [Description("The Due Date.")]
        public DateTime? DueDate
        {
            get { return _dueDate; }
            set
            {
                _dueDate = value;
                OnPropertyChanged("DueDate", true);
            }
        }

        /// <summary>
        /// Gets or sets the planned.
        /// </summary>
        /// <value>
        /// The planned.
        /// </value>
        [Category("Properties")]
        [DisplayName("Planned")]
        [Description("The Planned.")]
        public int Planned
        {
            get { return _planned; }
            set
            {
                _planned = value;
                OnPropertyChanged("Planned", true);
            }
        }

        /// <summary>
        /// Gets or sets the actual.
        /// </summary>
        /// <value>
        /// The actual.
        /// </value>
        [Category("Properties")]
        [DisplayName("Actual")]
        [Description("The Actual.")]
        public int Actual
        {
            get { return _actual; }
            set
            {
                _actual = value;
                OnPropertyChanged("Actual", true);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [closed].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [closed]; otherwise, <c>false</c>.
        /// </value>
        [Category("Properties")]
        [DisplayName("Closed")]
        [Description("Closed.")]
        public bool Closed
        {
            get { return _closed; }
            set
            {
                _closed = value;
                OnPropertyChanged("Closed", true);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [enabled].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [enabled]; otherwise, <c>false</c>.
        /// </value>
        [Category("Properties")]
        [DisplayName("Enabled")]
        [Description("Enable / disable the production plan.")]
        public bool Enabled
        {
            get { return _enabled; }
            set
            {
                _enabled = value;
                OnPropertyChanged("Enabled", true);
            }
        }

        /// <summary>
        /// Gets or sets the sort order.
        /// </summary>
        /// <value>
        /// The sort order.
        /// </value>
        public int SortOrder
        {
            get { return _sortOrder; }
            set
            {
                _sortOrder = value;
                OnPropertyChanged("SortOrder", true);
            }
        }

        /// <summary>
        /// Gets or sets the created by.
        /// </summary>
        /// <value>
        /// The created by.
        /// </value>
        [Category("Update History")]
        [DisplayName("Created By")]
        [Description("User who created the production plan in VisiAdmin.")]
        public string CreatedBy
        {
            get { return _createdBy; }
            set
            {
                _createdBy = value;
                OnPropertyChanged("CreatedBy");
            }
        }

        /// <summary>
        /// Gets or sets the created date.
        /// </summary>
        /// <value>
        /// The created date.
        /// </value>
        [Category("Update History")]
        [DisplayName("Created On")]
        [Description("Date when the production plan was created in VisiAdmin.")]
        public string CreatedDate
        {
            get { return _createdDate; }
            set
            {
                _createdDate = value;
                OnPropertyChanged("CreatedDate");
            }
        }

        /// <summary>
        /// Gets or sets the last updated by.
        /// </summary>
        /// <value>
        /// The last updated by.
        /// </value>
        [Category("Update History")]
        [DisplayName("Updated By")]
        [Description("User who last edited the production plan in VisiAdmin.")]
        public string LastUpdatedBy
        {
            get { return _lastUpdatedBy; }
            set
            {
                _lastUpdatedBy = value;
                OnPropertyChanged("LastUpdatedBy");
            }
        }

        /// <summary>
        /// Gets or sets the last updated date.
        /// </summary>
        /// <value>
        /// The last updated date.
        /// </value>
        [Category("Update History")]
        [DisplayName("Updated On")]
        [Description("Date when the production plan was last edited in VisiAdmin.")]
        public string LastUpdatedDate
        {
            get { return _lastUpdatedDate; }
            set
            {
                _lastUpdatedDate = value;
                OnPropertyChanged("LastUpdatedDate");
            }
        }

        /// <summary>
        /// Gets or sets the cell description.
        /// </summary>
        /// <value>
        /// The cell description.
        /// </value>
        public string CellDescription
        {
            get { return _cellDescription; }
            set
            {
                _cellDescription = value;
                OnPropertyChanged("CellDescription");
            }
        }

        /// <summary>
        /// Gets or sets the product description.
        /// </summary>
        /// <value>
        /// The product description.
        /// </value>
        public string ProductSku
        {
            get { return _product_sku; }
            set
            {
                _product_sku = value;
                OnPropertyChanged("ProductSku");
            }
        }

        /// <summary>
        /// Gets or sets the braider product description.
        /// </summary>
        /// <value>
        /// The braider product description.
        /// </value>
        public string BraiderProductDescription
        {
            get { return _braiderProductDescription; }
            set
            {
                _braiderProductDescription = value;
                OnPropertyChanged("BraiderProductDescription");
            }
        }

        #endregion

        #region IDataErrorInfo Members
        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <param name="columnName">Name of the column.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public string this[string columnName]
        {
            get
            {
                if (!ShouldValidate)
                    return string.Empty;

                if ((columnName == "CellId") && CellId <=0)
                    return ValidationMessages.CellRequired;

                if (columnName == "ProductId" && ProductId <= 0)
                    return ValidationMessages.ProductRequired;

                if (columnName == "DueDate" && (DueDate == null || DueDate == DateTime.MinValue))
                    return ValidationMessages.DueDateRequired;

                if (columnName == "WorkOrder" && string.IsNullOrEmpty(WorkOrder))
                    return ValidationMessages.WorkOrderRequired;
                return string.Empty;
            }
        }

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        /// <returns>An error message indicating what is wrong with this object. The default is an empty string ("").</returns>
        public string Error { get; private set; } 
        #endregion

        #region Override Equals methods
        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        /// <param name="other">The other.</param>
        /// <returns></returns>
        public bool Equals(ProductionPlanModel other)
        {
            if (ReferenceEquals(null, other))
                return false;
            if (ReferenceEquals(this, other))
                return true;
            return string.Equals(CellId, other.CellId)
                   && string.Equals(WorkOrder, other.WorkOrder)
                   && ProductId ==  other.ProductId
                   && (BraiderProductId??0) ==  (other.BraiderProductId??0)
                   && CellId ==  other.CellId
                   && DateTime.Equals(DueDate, other.DueDate)
                   && Planned == other.Planned
                   && Actual == other.Actual
                   && Enabled == other.Enabled
                   && Closed == other.Closed
                   && SortOrder == other.SortOrder;
        }

        /// <summary>
        /// Determines whether the specified {see cref="System.Object" }, is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != GetType())
                return false;
            return Equals((ProductionPlanModel)obj);
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            unchecked
            {
                var result = 0;
                result = (result * 397) ^ CellId.GetHashCode();
                result = (result * 397) ^ (WorkOrder ?? string.Empty).GetHashCode();
                result = (result * 397) ^ ProductId.GetHashCode();
                result = (result * 397) ^ (BraiderProductId!=null ? BraiderProductId.GetHashCode(): 0.GetHashCode());
                result = (result * 397) ^ DueDate.GetHashCode();
                result = (result * 397) ^ Planned.GetHashCode();
                result = (result * 397) ^ Enabled.GetHashCode();
                result = (result * 397) ^ Actual.GetHashCode();
                result = (result * 397) ^ Closed.GetHashCode();
                result = (result * 397) ^ SortOrder.GetHashCode();
                return result;
            }
        }
        #endregion
    }
}
